import React, { PureComponent } from 'react';
import classNames from 'classnames';
import './style.less';

const arrow_left = require('./arrow_left.svg');
const arrow_right = require('./arrow_right.svg');
const d_left = require('./d_left.svg');
const d_right = require('./d_right.svg');

// interface DateViewProps {
//     /**
//      * 默认选中哪一天
//      */
//     defaultSelectDay?: Date;
//     /**
//      * 点击日期回调
//      *
//      * @param day 2018-04-12
//      */
//     onDayClick?: Function;
//     /**
//      * 点击下一个月回调
//      */
//     onNextMonth?: (date: string) => void;
//     /**
//      * 点击上一个月回调
//      */
//     onPreMonth?: (date: string) => void;
//     /**
//      * 禁用天
//      *
//      * 类型: 2018-04-12
//      */
//     disableDay?: Array<string>;
//     /**
//      * 为true时，disableDay为可点击，其余为disable
//      */
//     disableFlip?: boolean;
//     /**
//      * 周名称排序
//      * 默认周日开始
//      * true为周一开始
//      */
//     weekShort?: boolean;
//     /**
//      * 以当天为基准，实现当前以前的日期可选
//      */
//     todayAsBefore?: boolean;
// }

// interface DateViewState {
//     toDay: string;
//     checkedDate: any;
//     day: number;
//     month: number;
//     year: number;
//     days: Array<{
//         str: string | number;
//         date: string | number;
//     }>;
// }

// type DateNum = number;

class DateView extends PureComponent {
    static defaultProps = {
        onDayClick: () => {}
    };

    _currentDate = new Date();

    disableDay = [];

    ZH_MONTH = [
        '1月',
        '2月',
        '3月',
        '4月',
        '5月',
        '6月',
        '7月',
        '8月',
        '9月',
        '10月',
        '11月',
        '12月'
    ];

    ZH_WEEK = ['日', '一', '二', '三', '四', '五', '六'];

    SHOW_WEEK_GRAY = new Set([0, 6]);

    constructor(props) {
        super(props);

        const initDate =
            this.props.defaultSelectDay &&
            new Date(
                Date.parse(this.props.defaultSelectDay.replace(/-/g, '/'))
            );
        const toDay = initDate || new Date();
        const day = toDay.getDate();
        const month = toDay.getMonth();
        const year = toDay.getFullYear();

        if (props.weekShort) {
            const week = this.ZH_WEEK.shift();
            this.ZH_WEEK.push(week);
            this.SHOW_WEEK_GRAY.clear();
            this.SHOW_WEEK_GRAY.add(5).add(6);
        }

        this.disableDay = new Set(props.disableDay);

        this.state = {
            toDay: this.format(toDay),
            checkedDate: this.format(toDay),
            day,
            month,
            year,
            days: this.draw(year, month, day),
            show: this.props.show
        };

        this.handleDay = this.handleDay.bind(this);
        this.nextMonth = this.nextMonth.bind(this);
        this.preMonth = this.preMonth.bind(this);
        this.nextYear = this.nextYear.bind(this);
        this.preYear = this.preYear.bind(this);
    }

    componentWillReceiveProps(props) {
        this.disableDay = new Set(props.disableDay);
        if (props.show) {
            const initDate =
                this.props.defaultSelectDay &&
                new Date(
                    Date.parse(this.props.defaultSelectDay.replace(/-/g, '/'))
                );
            const toDay = initDate || new Date();
            const day = toDay.getDate();
            const month = toDay.getMonth();
            const year = toDay.getFullYear();

            if (props.weekShort) {
                const week = this.ZH_WEEK.shift();
                this.ZH_WEEK.push(week);
                this.SHOW_WEEK_GRAY.clear();
                this.SHOW_WEEK_GRAY.add(5).add(6);
            }

            this.setState({
                toDay: this.format(toDay),
                checkedDate: this.format(toDay),
                day,
                month,
                year,
                days: this.draw(year, month, day),
                show: this.props.show
            });
        }
    }

    draw(year, month, day) {
        // 当月第一天是周几
        let toMonthFirWeek = new Date(year, month, 1).getDay();

        if (this.props.weekShort) {
            toMonthFirWeek += 6;

            if (toMonthFirWeek > 6) {
                toMonthFirWeek = toMonthFirWeek - 7;
            }
        }

        // 当月总共多少天
        const toMonthAllDay = new Date(year, month + 1, 0).getDate();

        // 行数
        const bodyLine = Math.ceil((toMonthAllDay + toMonthFirWeek) / 7);

        const days = [];

        for (let i = 0; i < bodyLine; i++) {
            for (let k = 0; k < 7; k++) {
                const idx = i * 7 + k;
                const date = idx - toMonthFirWeek + 1;

                if (date <= 0 || date > toMonthAllDay) {
                    days.push({
                        str: date,
                        date: ''
                    });
                } else {
                    days.push({
                        str: this.format(new Date(year, month, date)),
                        date
                    });
                }
            }
        }

        return days;
    }

    format(date) {
        const day = date.getDate();
        const month = date.getMonth();
        const year = date.getFullYear();

        function p(s) {
            return s < 10 ? '0' + s : s;
        }

        return `${year}-${p(month + 1)}-${p(day)}`;
    }

    /**
     * 下一个月
     */
    nextMonth() {
        const { month, year } = this.state;
        const { onNextMonth = () => {} } = this.props;
        let newMonth = month + 1;
        let newYear = year;
        if (month >= 11) {
            newMonth = 0;
            newYear += 1;
        }
        this.setState(
            {
                days: this.draw(newYear, newMonth, 1),
                month: newMonth,
                year: newYear
            },
            () => {
                onNextMonth(this.format(new Date(newYear, newMonth, 1)));
            }
        );
    }

    /**
     * 上一个月
     */
    preMonth() {
        const { month, year } = this.state;
        const { onPreMonth = () => {} } = this.props;
        let newMonth = month - 1;
        let newYear = year;
        if (month < 1) {
            newMonth = 11;
            newYear -= 1;
        }
        this.setState(
            {
                days: this.draw(newYear, newMonth, 1),
                month: newMonth,
                year: newYear
            },
            () => {
                onPreMonth(this.format(new Date(newYear, newMonth, 1)));
            }
        );
    }

    /**
     * 下一年
     */
    nextYear() {
        const { month, year } = this.state;
        const { onNextYear = () => {} } = this.props;
        let newMonth = month;
        let newYear = year + 1;
        this.setState(
            {
                days: this.draw(newYear, newMonth, 1),
                month: newMonth,
                year: newYear
            },
            () => {
                onNextYear(this.format(new Date(newYear, newMonth, 1)));
            }
        );
    }

    /**
     * 上一年
     */
    preYear() {
        const { month, year } = this.state;
        const { onPreYear = () => {} } = this.props;
        let newMonth = month;
        let newYear = year - 1;
        this.setState(
            {
                days: this.draw(newYear, newMonth, 1),
                month: newMonth,
                year: newYear
            },
            () => {
                onPreYear(this.format(new Date(newYear, newMonth, 1)));
            }
        );
    }

    handleDay(e) {
        const value = e.currentTarget.getAttribute('data-day');
        this.setState({
            toDay: value,
            checkedDate: value
        });
        this.props.onDayClick(value);
    }

    render() {
        const { year, month, days, checkedDate } = this.state;
        const { ZH_MONTH, SHOW_WEEK_GRAY } = this;
        const {
            lang = { cancelBtn: '取消', okBtn: '确认' },
            title = '请选择',
            onOk,
            onCancel,
            show
        } = this.props;

        const animateSty = classNames({
            'Date-animate-slide-up': show,
            'Date-animate-slide-down': !show
        });

        return (
            <div className={`Date ${animateSty}`}>
                <div className="Date-ctrl">
                    <div className="left" onClick={() => onCancel()}>
                        {lang.cancelBtn}
                    </div>
                    <div className="title">{title}</div>
                    <div className="right" onClick={() => onOk(checkedDate)}>
                        {lang.okBtn}
                    </div>
                </div>
                <div className="Date-header">
                    <div className="Date-header-arrow-box">
                        <img
                            src={d_left}
                            className="Date-header-arrow-d"
                            alt="arrow_left"
                            onClick={this.preYear}
                        />
                        <img
                            src={arrow_left}
                            className="Date-header-arrow"
                            alt="arrow_left"
                            onClick={this.preMonth}
                        />
                    </div>
                    <div>{`${year}年${ZH_MONTH[month]}`}</div>
                    <div className="Date-header-arrow-box">
                        <img
                            src={arrow_right}
                            className="Date-header-arrow"
                            alt="arrow_right"
                            onClick={this.nextMonth}
                        />
                        <img
                            src={d_right}
                            className="Date-header-arrow-d"
                            alt="arrow_right"
                            onClick={this.nextYear}
                        />
                    </div>
                </div>
                <div className="Date-week">
                    {this.ZH_WEEK.map((week, idx) => (
                        <div
                            className={
                                SHOW_WEEK_GRAY.has(idx)
                                    ? 'Date-week-gray'
                                    : undefined
                            }
                            key={idx}
                        >
                            {week}
                        </div>
                    ))}
                </div>
                <div className="Date-body">
                    <div className="Date-body-head">
                        <span className="Date-body-head-num">{month + 1}</span>
                        <span>月</span>
                    </div>
                    <div className="Date-body-content">
                        {days.map(day => {
                            const { str, date } = day;
                            const {
                                disableFlip = false,
                                todayAsBefore = true
                            } = this.props;
                            const _drawDate = new Date(str);
                            let isDisable = false;
                            if (todayAsBefore) {
                                if (
                                    this._currentDate.getTime() -
                                        1000 * 60 * 60 * 24 <
                                    _drawDate.getTime()
                                )
                                    isDisable = false;
                                else isDisable = true;
                            } else {
                                isDisable = this.disableDay.has(str);
                                isDisable === disableFlip
                                    ? !isDisable
                                    : isDisable;
                            }
                            return (
                                <div
                                    className={classNames(
                                        'Date-day',
                                        {
                                            'Date-today':
                                                checkedDate === str &&
                                                !isDisable
                                        },
                                        { 'Date-disable-day': isDisable }
                                    )}
                                    key={date || str}
                                    data-day={str}
                                    onClick={
                                        !isDisable && date
                                            ? this.handleDay
                                            : undefined
                                    }
                                >
                                    {date}
                                </div>
                            );
                        })}
                    </div>
                </div>
            </div>
        );
    }
}

export default DateView;
